#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/string.hpp>
#include "json/json.h"
#include "MetaObjectTrans.h"

namespace boost {
namespace serialization {

template<class Archive>
void serialize(Archive & ar, gitstore::Object & d, const unsigned int version)
{
    ar & d.name;
    ar & d.type;
    ar & d.subtype;
    ar & d.note;
    ar & d.date;
    ar & d.main_branch;
}

template<class Archive>
void serialize(Archive & ar, gitstore::Node & d, const unsigned int version)
{
    ar & d.version;
    ar & d.type;
    ar & d.note;
    ar & d.date;
    ar & d.parents;
    ar & d.children;
    ar & d.obj_name;
}

template<class Archive>
void serialize(Archive & ar, gitstore::Branch & d, const unsigned int version)
{
    ar & d.name;
    ar & d.type;
    ar & d.note;
    ar & d.date;
    ar & d.cur_version;
    ar & d.obj_name;
}

} // namespace serialization
}
namespace gitstore {
CObjectCodeTransBase::CObjectCodeTransBase() {

}

CObjectCodeTransBase::~CObjectCodeTransBase() {

}

CObjectCodeJsonTrans::CObjectCodeJsonTrans() {

}

CObjectCodeJsonTrans::~CObjectCodeJsonTrans() {

}

ErrorStatus CObjectCodeJsonTrans::encodeObject(const Object& object, std::string &json_string) {
    Json::Value json_value;
    json_value["date"] = object.date;
    json_value["note"] = object.note;
    json_value["name"] = object.name;
    json_value["type"] = object.type;
    json_value["main_branch"] = object.main_branch;
    json_string = json_value.toStyledString();
    return Success;
}

ErrorStatus CObjectCodeJsonTrans::decodeObject(Object& object, const std::string &json_string) {
    Json::Reader reader;
    Json::Value json_value;
    reader.parse(json_string, json_value);
    object.date = json_value["date"].asInt64();
    object.note = json_value["note"].asString();
    object.name = json_value["name"].asString();
    object.type = json_value["type"].asInt();
    object.main_branch = json_value["main_branch"].asString();
    return Success;
}

ErrorStatus CObjectCodeJsonTrans::encodeBranch(const Branch& branch, std::string &json_string) {
    Json::Value json_value;
    json_value["date"] = branch.date;
    json_value["note"] = branch.note;
    json_value["name"] = branch.name;
    json_value["cur_version"] = branch.cur_version;
    json_value["type"] = branch.type;
    json_value["obj_name"] = branch.obj_name;
    json_string = json_value.toStyledString();
    return Success;
}

ErrorStatus CObjectCodeJsonTrans::decodeBranch(Branch& branch, const std::string &json_string) {
    Json::Reader reader;
    Json::Value json_value;
    reader.parse(json_string, json_value);
    branch.date = json_value["date"].asInt64();
    branch.note = json_value["note"].asString();
    branch.name = json_value["name"].asString();
    branch.cur_version = json_value["cur_version"].asString();
    branch.type = json_value["type"].asInt();
    branch.obj_name = json_value["obj_name"].asString();
    return Success;
}

ErrorStatus CObjectCodeJsonTrans::encodeNode(const Node& node, std::string &json_string) {
    Json::Value json_value;
    json_value["date"] = node.date;
    json_value["note"] = node.note;
    json_value["version"] = node.version;
    json_value["type"] = node.type;
    json_value["obj_name"] = node.obj_name;
    json_value["parents"] = Json::arrayValue;
    for (auto &parent : node.parents) {
        json_value["parents"].append(parent);
    }
    json_value["children"] = Json::arrayValue;
    for (auto &child : node.children) {
        json_value["children"].append(child);
    }
    json_string = json_value.toStyledString();
    return Success;
}

ErrorStatus CObjectCodeJsonTrans::decodeNode(Node& node, const std::string &json_string) {
    Json::Reader reader;
    Json::Value json_value;
    reader.parse(json_string, json_value);
    node.date = json_value["date"].asInt64();
    node.note = json_value["note"].asString();
    node.version = json_value["version"].asString();
    node.type = json_value["type"].asInt();
    node.obj_name = json_value["obj_name"].asString();
    node.parents.clear();
    node.parents.shrink_to_fit();
    for (unsigned int i = 0; i < json_value["parents"].size(); ++i) {
        node.parents.emplace_back(json_value["parents"][i].asString());
    }
    node.children.clear();
    node.children.shrink_to_fit();
    for (unsigned int i = 0; i < json_value["children"].size(); ++i) {
        node.children.emplace_back(json_value["children"][i].asString());
    }
    return Success;
}

CObjectCodeBoostSerializationTrans::CObjectCodeBoostSerializationTrans() {

}

CObjectCodeBoostSerializationTrans::~CObjectCodeBoostSerializationTrans() {

}



ErrorStatus CObjectCodeBoostSerializationTrans::encodeObject(const Object& object, std::string &en_string) {
    std::ostringstream ss;
    boost::archive::binary_oarchive ob(ss);
    ob << object;
    en_string.assign(ss.str());
    return Success;
}

ErrorStatus CObjectCodeBoostSerializationTrans::decodeObject(Object& object, const std::string &de_string) {
    std::istringstream ss(de_string);
    boost::archive::binary_iarchive ob(ss);
    ob >> object;
    return Success;
}

ErrorStatus CObjectCodeBoostSerializationTrans::encodeBranch(const Branch& branch, std::string &en_string) {
    std::ostringstream ss;
    boost::archive::binary_oarchive ob(ss);
    ob << branch;
    en_string.assign(ss.str());
    return Success;
}

ErrorStatus CObjectCodeBoostSerializationTrans::decodeBranch(Branch& branch, const std::string &de_string) {
    std::istringstream ss(de_string);
    boost::archive::binary_iarchive ob(ss);
    ob >> branch;
    return Success;
}

ErrorStatus CObjectCodeBoostSerializationTrans::encodeNode(const Node& node, std::string &en_string) {
    std::ostringstream ss;
    boost::archive::binary_oarchive ob(ss);
    ob << node;
    en_string.assign(ss.str());
    return Success;
}

ErrorStatus CObjectCodeBoostSerializationTrans::decodeNode(Node& node, const std::string &de_string) {
    std::istringstream ss(de_string);
    boost::archive::binary_iarchive ob(ss);
    ob >> node;
    return Success;
}
}
